package com.qfx.system.service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.quartz.CronScheduleBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.ObjectAlreadyExistsException;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qfx.common.bean.MessageBean;
import com.qfx.common.service.BaseService;
import com.qfx.common.utils.Page;
import com.qfx.system.dao.QrtzJobDetailsDao;
import com.qfx.system.vo.QuartzEntity;

/**
 * <h5>描述:Quartz业务操作类</h5>
 * 
 * @author qfx	2019年8月16日 
 */
@Service
public class QuartzService extends BaseService {

	@Autowired
	QrtzJobDetailsDao qrtzJobDetailsDao;
	@Autowired
    private Scheduler scheduler;
	
	/**
	 * <h5>功能:获取定时任务列表</h5>
	 * 
	 * @author qfx	@date 2019年8月16日
	 * @return 
	 */
	public Map<String, Object> list() {
		// 获取从request中传递过来的参数信息
		Map<String, Object> paramMap = getMaps();
		// 获取分页信息
		Page page = getPage(paramMap);
		PageHelper.startPage(page.getCurrentPage(), page.getPageSize());
		List<QuartzEntity> list = qrtzJobDetailsDao.selectAll(paramMap);
		
		PageInfo<QuartzEntity> pageInfo = new PageInfo<QuartzEntity>(list);
		//获得总条数
		long total = pageInfo.getTotal();
		
		Map<String, Object> dataMap = new HashMap<String, Object>();
		dataMap.put("code", 0);
		dataMap.put("count", total);
		dataMap.put("data", pageInfo.getList());

		return dataMap;
	}

	/**
	 * <h5>功能:验证任务名称是否已经存在</h5>
	 * 
	 * @author qfx	@date 2019年8月16日
	 * @return 
	 */
	public MessageBean validateJobName() {
		MessageBean messageBean = new MessageBean();
		int count = Integer.parseInt(list().get("count").toString());
		if (count > 0) {
			messageBean.setResult(false);
			messageBean.setMessage("当前任务名称已存在");
		}
		return messageBean;
	}
	
	// ==================== 往下为Quartz业务方法 ====================

	/**
	 * <h5>功能:重新编辑定时任务</h5>
	 * 
	 * @author qfx	@date 2019年8月16日
	 * @param quartz
	 * @return 
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public MessageBean edit(QuartzEntity quartz) {
		MessageBean messageBean = new MessageBean();
		String processingType ="新增";
		try {
			JobDataMap jobDataMap = null;
			// 1.验证是否是修改操作,如果是,则删除旧的任务
			if(quartz.getOldJobGroup()!= null && quartz.getOldJobGroup()!= ""){
				processingType = "修改";
	        	JobKey key =JobKey.jobKey(quartz.getOldJobName(),quartz.getOldJobGroup());
	        	JobDetail jobDetail = scheduler.getJobDetail(key);
	        	jobDataMap = jobDetail.getJobDataMap();
	        	for (String key1 : jobDataMap.keySet()) {
	        		System.out.println(key1 + ":" + jobDataMap.get(key1));
	        	}
	        	key = new JobKey(quartz.getOldJobName(),quartz.getOldJobGroup());
	        	scheduler.deleteJob(key);
	        }
			// 2.开始构建新的定时任务
	        Class cls = Class.forName(quartz.getJobClassName()) ;
	        cls.newInstance();
	        // 2.1 构建新的job信息
	        JobDetail job = JobBuilder.newJob(cls)
	        		.withIdentity(quartz.getJobName(), quartz.getJobGroup())	//job名称和分组名称
	        		.withDescription(quartz.getDescription())	//描述信息
	        		.build();
	        // 2.2 添加JobDataMap数据,如果没有则不需要配置
//			JobDataMap jobDataMap = new JobDataMap();
//			jobDataMap.put("userName", "zhangsan");
//			jobDataMap.put("age", 18);
//        	job.getJobDataMap().putAll(jobDataMap);
	        if (jobDataMap != null) {
	        	job.getJobDataMap().putAll(jobDataMap);
			}
	        
			// 2.3 设置触发时间点
			CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder
					.cronSchedule(quartz.getCronExpression())
					// 表示等待下次Cron触发频率到达时刻开始按照Cron频率依次执行(即暂停期间的不再执行,去掉则表示补充执行)
					.withMisfireHandlingInstructionDoNothing();
			// 2.4 设置触发器
			Trigger trigger = TriggerBuilder
					.newTrigger()
					.withIdentity("trigger" + quartz.getJobName(),quartz.getJobGroup()) //job名称和分组名称
//					// 使用 Cron 表达式时,StartNow 方法不会起任何效果,Cron 有其自己的执行时间。目前看来 StartNow 应该只适用于 SimpleTrigger 触发器
//					.startNow() // 一旦加入scheduler,立即生效()
					.withSchedule(cronScheduleBuilder) //执行时间
					.build();
	        // 2.5 交由Scheduler安排触发
	        scheduler.scheduleJob(job, trigger);
	        messageBean.setMessage("定时任务[" + quartz.getJobName() + "]" + processingType +"成功~!");
		} catch (ClassNotFoundException e) {
			messageBean.setResult(false);
			messageBean.setMessage("要" + processingType +"的任务类[" + quartz.getJobClassName() + "]不存在,定时任务" + processingType +"失败~!");
			e.printStackTrace();
		} catch(ObjectAlreadyExistsException e){
			messageBean.setResult(false);
			messageBean.setMessage("当前分组定时任务[" + quartz.getJobName() + "]已存在,操作失败~!");
			e.printStackTrace();
		} catch (SchedulerException e) {
			messageBean.setResult(false);
			messageBean.setMessage(processingType +"定时任务[" + quartz.getJobName() + "]设置失败,执行时间配置了不合法或过去的时间,该任务永远不会被执行~!");
			e.printStackTrace();
		} catch (Exception e) {
			messageBean.setResult(false);
			messageBean.setMessage(processingType +"定时任务[" + quartz.getJobName() + "]发生异常,操作失败~!");
			e.printStackTrace();
			log.error("{}定时任务[{}]发生异常,操作失败~!", processingType, quartz.getJobName(), e);
		}
		return messageBean;
	}
	
	/**
	 * <h5>功能:删除一个定时任务</h5>
	 * 
	 * @author qfx	@date 2019年8月16日
	 * @param quartz
	 * @return 
	 */
	public MessageBean del(QuartzEntity quartz) {
		MessageBean messageBean = new MessageBean();
		try {  
            TriggerKey triggerKey = TriggerKey.triggerKey(quartz.getJobName(), quartz.getJobGroup());  
            // 停止触发器  
            scheduler.pauseTrigger(triggerKey);  
            // 移除触发器  
            scheduler.unscheduleJob(triggerKey);  
            // 删除任务  
            boolean flag = scheduler.deleteJob(JobKey.jobKey(quartz.getJobName(), quartz.getJobGroup()));
            if (flag) {
            	System.out.println("removeJob:"+JobKey.jobKey(quartz.getJobName()));
            	messageBean.setMessage("定时任务[" + quartz.getJobName() + "]删除成功~!");
			} else {
				System.out.println("removeJob:"+JobKey.jobKey(quartz.getJobName())+"fail");
				messageBean.setMessage("定时任务[" + quartz.getJobName() + "]删除失败~!");
			}
            System.out.println("removeJob:"+JobKey.jobKey(quartz.getJobName()));
            messageBean.setMessage("定时任务[" + quartz.getJobName() + "]删除成功~!");
        } catch (Exception e) {
        	messageBean.setResult(false);
			messageBean.setMessage("删除定时任务[" + quartz.getJobName() + "]发生异常,操作失败~!");
        	e.printStackTrace();
        	log.error("删除定时任务[{}]发生异常,操作失败~!", quartz.getJobName(), e);
        }  
		return messageBean;
	}
	
	/**
	 * <h5>功能:暂停一个定时任务</h5>
	 * 
	 * @author qfx	@date 2019年8月16日
	 * @param quartz
	 * @return 
	 */
	public MessageBean pause(QuartzEntity quartz) {
		MessageBean messageBean = new MessageBean();
		try {
			JobKey key = new JobKey(quartz.getJobName(), quartz.getJobGroup());
			scheduler.pauseJob(key);
			messageBean.setMessage("定时任务[" + quartz.getJobName() + "]停止成功~!");
		} catch (SchedulerException e) {
			messageBean.setResult(false);
			messageBean.setMessage("停止定时任务[" + quartz.getJobName() + "]发生异常,操作失败~!");
			e.printStackTrace();
			log.error("停止定时任务[{}]发生异常,操作失败~!", quartz.getJobName(), e);
		}
		return messageBean;
	}
	
	/**
	 * <h5>功能:重新开始一个定时任务</h5>
	 * 
	 * @author qfx	@date 2019年8月16日
	 * @param quartz
	 * @return 
	 */
	public MessageBean resume(QuartzEntity quartz) {
		MessageBean messageBean = new MessageBean();
		try {
		     JobKey key = new JobKey(quartz.getJobName(),quartz.getJobGroup());
		     scheduler.resumeJob(key);
		     messageBean.setMessage("定时任务[" + quartz.getJobName() + "]恢复成功~!");
		} catch (SchedulerException e) {
			messageBean.setResult(false);
			messageBean.setMessage("恢复定时任务[" + quartz.getJobName() + "]发生异常,操作失败~!");
			e.printStackTrace();
			log.error("恢复定时任务[{}]发生异常,操作失败~!", quartz.getJobName(), e);
		}
		return messageBean;
	}
	
	/**
	 * <h5>功能:暂停所有定时任务</h5>
	 * 
	 * @author qfx	@date 2019年8月16日
	 * @return 
	 */
	public MessageBean pauseAll() {
		MessageBean messageBean = new MessageBean();
        try {
			if (!scheduler.isShutdown()) {  
				scheduler.pauseAll(); 
			}
			messageBean.setMessage("定时任务全部暂停执行成功~!");
		} catch (SchedulerException e) {
			messageBean.setResult(false);
			messageBean.setMessage("定时任务全部暂停执行发生异常,操作失败~!");
			e.printStackTrace();
			log.error("定时任务全部暂停执行发生异常,操作失败~!", e);
		}  
		return messageBean;
	}
	
	/**
	 * <h5>功能:重新开启所有定时任务</h5>
	 * 
	 * @author qfx	@date 2019年8月16日
	 * @return 
	 */
	public MessageBean resumeAll() {
		MessageBean messageBean = new MessageBean();
		try {
			scheduler.resumeAll();
			messageBean.setMessage("定时任务全部开启执行成功~!");
		} catch (SchedulerException e) {
			messageBean.setResult(false);
			messageBean.setMessage("定时任务全部开启执行发生异常,操作失败~!");
			e.printStackTrace();
			log.error("定时任务全部开启执行发生异常,操作失败~!", e);
		}  
		return messageBean;
	}
}
